package cn.xyfmzmy.proxy;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 生成MyInferface实现类的工厂
 * 动态代理的实现逻辑:
 * 1.生成接口相应实现类的java文件的字符串;
 * 2.根据字符串生成相应的java文件;
 * 3.编译java文件,生成对应的class字节码文件
 * 4.利用反射机制,用类加载器加载class文件,生成相应的java实现类对象(proxy对象),再执行相关方法
 *
 * 动态代理的核心: 给予了我们创建对象(实现类)的能力(无需创建出对象的文件)，既可以是对现有对象的增强，也可以是凭空创造出来的对象
 */
public class MyInerfaceFactory {

    private static final AtomicInteger count = new AtomicInteger();

    // 创建java文件
    private static File createJavaFile(String className,MyHandler myHandler) throws IOException {
        String func1Body = myHandler.functionBody("func1");
        String func2Body = myHandler.functionBody("func2");
        String func3Body = myHandler.functionBody("func3");
        String content = "package cn.xyfmzmy.proxy;\n" +
                "\n" +
                "public class "+ className +" implements MyInterface{\n" +
                "    MyInterface myInterface; \n" +
                "    @Override\n" +
                "    public void func1() {\n" +
                "        "+func1Body+"\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public void func2() {\n" +
                "        "+func2Body+"\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public void func3() {\n" +
                "        "+func3Body+"\n" +
                "    }\n" +
                "}\n";
        File javaFile = new File(className + ".java");
        Files.writeString(javaFile.toPath(),content);
        return javaFile;
    }

    // 获取类名
    private static String getClassName(){
        return "MyInterface$proxy" + count.incrementAndGet();
    }

    // 获取方法体
    private static String functionBody(String methodName){
        return "System.out.println(\""+ methodName + "\");";
    }

    // 创建MyInterface的实例对象
    private static MyInterface newInstance(String className,MyHandler myHandler) throws Exception {
        Class<?> aClass = MyInerfaceFactory.class.getClassLoader().loadClass(className);    // 用类加载器获取Class对象
        Constructor<?> constructor = aClass.getConstructor();                               // 获取构造方法
        MyInterface proxy = (MyInterface) constructor.newInstance();                        // 用构造方法创建对象
        // 给新生成的代理对象proxy赋值,是把 "myHandler里的原代理对象" 赋值给 "新代理对象proxy",实现增强
        myHandler.setProxy(proxy);
        return proxy;
    }

    // 对外提供的创建代理对象方法
    public static MyInterface createProxyObject(MyHandler myHandler) throws Exception {
        String className = getClassName();              // 获取类名
        File javaFile = createJavaFile(className,myHandler);      // 1.生成Java文件
        Compiler.compile(javaFile);                     // 2.编译Java文件 .java -> .class
        return newInstance("cn.xyfmzmy.proxy." + className,myHandler);      // 3.创建并返回示例对象(这里得传全类名)
    }



}
